home *** CD-ROM | disk | FTP | other *** search
/ Dr. Windows 3 / dr win3.zip / dr win3 / WINPROGS / WINSRC20.ZIP / WGENERAL.ASM < prev    next >
Assembly Source File  |  1990-09-29  |  13KB  |  516 lines

  1. ;    Generic assembler routines that have very little at all
  2. ;    to do with fractals.
  3. ;
  4. ;
  5. ; ---- 32-bit Multiply/Divide Routines (includes 16-bit emulation)
  6. ;
  7. ;    multiply()
  8. ;    divide()
  9. ;
  10.  
  11. .MODEL    medium,c
  12.  
  13. .8086
  14.  
  15. .DATA
  16.  
  17.  
  18. ; ************************ Public variables *****************************
  19.  
  20. public        overflow        ; Mul, Div overflow flag: 0 means none
  21.  
  22. ;        arrays declared here, used elsewhere
  23. ;        arrays not used simultaneously are deliberately overlapped
  24.  
  25. public        prefix, suffix, dstack, decoderline ; for the Decoder
  26. public        strlocn, teststring, block    ; used by the Encoder
  27. public        boxx, boxy, boxvalues        ; zoom-box arrays
  28. public        olddacbox            ; temporary DAC saves
  29. public        rlebuf                ; Used ty the TARGA En/Decoder
  30.  
  31. ; ************************* "Shared" array areas **************************
  32.  
  33. ; Short forms used in subsequent comments:
  34. ;   name........duration of use......................modules....................
  35. ;   encoder    "s"aving an image                    encoder.c
  36. ;   decoder    "r"estoring an image                 decoder.c, gifview.c
  37. ;   zoom    zoom box is visible             zoom.c, video.asm
  38. ;   vidswitch    temp during video mode setting         video.asm
  39. ;   vidreset    temp during video reset          prompts.c, fractint.c, rotate.c, cmdfiles.c
  40. ;   tgaview    restore of tga image             tgaview.c
  41. ;   solidguess    image gen with "g", not to disk      calcfrac.c
  42. ;   btm     image gen with "b", not to disk      calcfrac.c
  43.  
  44. block        label    byte        ; encoder(266)
  45. suffix        dw    2048 dup(0)    ; decoder(4k), vidswitch(256)
  46.  
  47. teststring    label    byte        ; encoder(100)
  48. dstack        dw    2048 dup(0)    ; decoder(4k), solidguess(4k), btm(2k)
  49.                     ;   zoom(2k)
  50.  
  51. strlocn     label    word        ; encoder(10k)
  52. prefix        label    word        ; decoder(8k), solidguess(6k)
  53. olddacbox    label    byte        ; vidreset(768)
  54. boxx        dw    2048 dup(0)    ; zoom(4k), tgaview(4k)
  55. boxy        dw    2048 dup(0)    ; zoom(4k)
  56. boxvalues    label    byte        ; zoom(2k)
  57. decoderline    db    2050 dup(0)    ; decoder(2049), btm(2k)
  58.  
  59. rlebuf        db    258 dup(0)    ; f16.c(258) .tga save/restore?
  60.  
  61. ; Internal Overflow flag
  62.  
  63. overflow    dw    0        ; overflow flag
  64.  
  65. .CODE
  66.  
  67.  
  68. ; =======================================================
  69. ;
  70. ;    32-bit integer multiply routine with an 'n'-bit shift.
  71. ;    Overflow condition returns 0x7fffh with overflow = 1;
  72. ;
  73. ;    long x, y, z, multiply();
  74. ;    int n;
  75. ;
  76. ;    z = multiply(x,y,n)
  77. ;
  78. ;    requires the presence of an external variable, 'cpu'.
  79. ;        'cpu' == 386 if a 386 is present.
  80.  
  81. .MODEL    medium,c
  82.  
  83. .8086
  84.  
  85. .DATA
  86.  
  87. extrn    cpu:word            ; cpu flag:     88 = 8088/8086
  88.                     ;        186 = 80188/186
  89.                     ;        286 = 80286
  90.                     ;        386 = 80386/486
  91. extrn    fpu:word            ; fpu flag:      0 = none
  92.                     ;         87 = 8087
  93.                     ;               287 = 80287
  94.                     ;        387 = 80387/(487)
  95.  
  96. temp    dw    5 dup(0)        ; temporary 64-bit result goes here
  97. sign    db    0            ; sign flag goes here
  98.  
  99. .CODE
  100.  
  101. multiply    proc    x:dword, y:dword, n:word
  102.  
  103.     cmp    cpu,386         ; go-fast time?
  104.     jne    slowmultiply        ; no.  yawn...
  105.  
  106. .386                    ; 386-specific code starts here
  107.  
  108.     mov    eax,x            ; load X into EAX
  109.     imul    y            ; do the multiply
  110.     mov    cx,n            ; set up the shift
  111.     cmp    cx,32            ; ugly klooge:    check for 32-bit shift
  112.     jb    short fastm1        ;  < 32 bits:  no problem
  113.     mov    eax,edx         ;  >= 32 bits:    manual shift
  114.     mov    edx,0            ;  ...
  115.     sub    cx,32            ;  ...
  116. fastm1: shrd    eax,edx,cl        ; shift down 'n' bits
  117.     js    fastm3
  118.     sar    edx,cl
  119.     jne    overmf
  120.     shld    edx,eax,16
  121.     ret
  122. fastm3: sar    edx,cl
  123.     inc    edx
  124.     jne    overmf
  125.     shld    edx,eax,16
  126.     ret
  127. overmf:
  128.     mov    ax,0ffffh        ; overflow value
  129.     mov    dx,07fffh        ; overflow value
  130.     mov    overflow,1        ; flag overflow
  131.     ret
  132.  
  133. .8086                    ; 386-specific code ends here
  134.  
  135. slowmultiply:                ; (sigh)  time to do it the hard way...
  136.     push    di
  137.     push    si
  138.  
  139.     mov    ax,0
  140.     mov    temp+4,ax        ; first, zero out the (temporary)
  141.     mov    temp+6,ax        ;  result
  142.     mov    temp+8,ax
  143.  
  144.     mov    bx,word ptr x        ; move X to SI:BX
  145.     mov    si,word ptr x+2        ;  ...
  146.     mov    cx,word ptr y        ; move Y to DI:CX
  147.     mov    di,word ptr y+2        ;  ...
  148.  
  149.     mov    sign,0            ; clear out the sign flag
  150.     cmp    si,0            ; is X negative?
  151.     jge    mults1            ;  nope
  152.     not    sign            ;  yup.  flip signs
  153.     not    bx            ;   ...
  154.     not    si            ;   ...
  155.     stc                ;   ...
  156.     adc    bx,ax            ;   ...
  157.     adc    si,ax            ;   ...
  158. mults1: cmp    di,0            ; is DI:CX negative?
  159.     jge    mults2            ;  nope
  160.     not    sign            ;  yup.  flip signs
  161.     not    cx            ;   ...
  162.     not    di            ;   ...
  163.     stc                ;   ...
  164.     adc    cx,ax            ;   ...
  165.     adc    di,ax            ;   ...
  166. mults2:
  167.  
  168.     mov    ax,bx            ; perform BX x CX
  169.     mul    cx            ;  ...
  170.     mov    temp,ax         ;  results in lowest 32 bits
  171.     mov    temp+2,dx        ;  ...
  172.  
  173.     mov    ax,bx            ; perform BX x DI
  174.     mul    di            ;  ...
  175.     add    temp+2,ax        ;  results in middle 32 bits
  176.     adc    temp+4,dx        ;  ...
  177.     jnc    mults3            ;  carry bit set?
  178.     inc    word ptr temp+6     ;  yup.  overflow
  179. mults3:
  180.  
  181.     mov    ax,si            ; perform SI * CX
  182.     mul    cx            ;  ...
  183.     add    temp+2,ax        ;  results in middle 32 bits
  184.     adc    temp+4,dx        ;  ...
  185.     jnc    mults4            ;  carry bit set?
  186.     inc    word ptr temp+6     ;  yup.  overflow
  187. mults4:
  188.  
  189.     mov    ax,si            ; perform SI * DI
  190.     mul    di            ;  ...
  191.     add    temp+4,ax        ; results in highest 32 bits
  192.     adc    temp+6,dx        ;  ...
  193.  
  194.     mov    cx,n            ; set up for the shift loop
  195.     cmp    cx,24            ; shifting by three bytes or more?
  196.     jl    multc1            ;  nope.  check for something else
  197.     sub    cx,24            ; quick-shift 24 bits
  198.     mov    ax,temp+3        ; load up the registers
  199.     mov    dx,temp+5        ;  ...
  200.     mov    si,temp+7        ;  ...
  201.     mov    bx,0            ;  ...
  202.     jmp    short multc4        ; branch to common code
  203. multc1: cmp    cx,16            ; shifting by two bytes or more?
  204.     jl    multc2            ;  nope.  check for something else
  205.     sub    cx,16            ; quick-shift 16 bits
  206.     mov    ax,temp+2        ; load up the registers
  207.     mov    dx,temp+4        ;  ...
  208.     mov    si,temp+6        ;  ...
  209.     mov    bx,0            ;  ...
  210.     jmp    short multc4        ; branch to common code
  211. multc2: cmp    cx,8            ; shifting by one byte or more?
  212.     jl    multc3            ;  nope.  check for something else
  213.     sub    cx,8            ; quick-shift 8 bits
  214.     mov    ax,temp+1        ; load up the registers
  215.     mov    dx,temp+3        ;  ...
  216.     mov    si,temp+5        ;  ...
  217.     mov    bx,temp+7        ;  ...
  218.     jmp    short multc4        ; branch to common code
  219. multc3: mov    ax,temp         ; load up the regs
  220.     mov    dx,temp+2        ;  ...
  221.     mov    si,temp+4        ;  ...
  222.     mov    bx,temp+6        ;  ...
  223. multc4: cmp    cx,0            ; done shifting?
  224.     je    multc5            ;  yup.  bail out
  225.  
  226. multloop:
  227.     shr    bx,1            ; shift down 1 bit, cascading
  228.     rcr    si,1            ;  ...
  229.     rcr    dx,1            ;  ...
  230.     rcr    ax,1            ;  ...
  231.     loop    multloop        ; try the next bit, if any
  232. multc5:
  233.     cmp    si,0            ; overflow time?
  234.     jne    overm1            ; yup.    Bail out.
  235.     cmp    bx,0            ; overflow time?
  236.     jne    overm1            ; yup.    Bail out.
  237.     cmp    dx,0            ; overflow time?
  238.     jl    overm1            ; yup.    Bail out.
  239.  
  240.     cmp    sign,0            ; should we negate the result?
  241.     je    mults5            ;  nope.
  242.     not    ax            ;  yup.  flip signs.
  243.     not    dx            ;   ...
  244.     mov    bx,0            ;   ...
  245.     stc                ;   ...
  246.     adc    ax,bx            ;   ...
  247.     adc    dx,bx            ;   ...
  248. mults5:
  249.     jmp    multiplyreturn
  250.  
  251. overm1:
  252.     mov    ax,0ffffh        ; overflow value
  253.     mov    dx,07fffh        ; overflow value
  254.     mov    overflow,1        ; flag overflow
  255.  
  256. multiplyreturn:             ; that's all, folks!
  257.     pop    si
  258.     pop    di
  259.     ret
  260. multiply    endp
  261.  
  262.  
  263. ; =======================================================
  264. ;
  265. ;    32-bit integer divide routine with an 'n'-bit shift.
  266. ;    Overflow condition returns 0x7fffh with overflow = 1;
  267. ;
  268. ;    long x, y, z, divide();
  269. ;    int n;
  270. ;
  271. ;    z = divide(x,y,n);    /* z = x / y; */
  272. ;
  273. ;    requires the presence of an external variable, 'cpu'.
  274. ;        'cpu' == 386 if a 386 is present.
  275.  
  276.  
  277. .8086
  278.  
  279. divide        proc    x:dword, y:dword, n:word
  280.  
  281.     push    di
  282.     push    si
  283.  
  284.     cmp    cpu,386         ; go-fast time?
  285.     jne    slowdivide        ; no.  yawn...
  286.  
  287. .386                    ; 386-specific code starts here
  288.  
  289.     mov    edx,x            ; load X into EDX (shifts to EDX:EAX)
  290.     mov    ebx,y            ; load Y into EBX
  291.  
  292.     mov    sign,0            ; clear out the sign flag
  293.     cmp    edx,0            ; is X negative?
  294.     jge    short divides1        ;  nope
  295.     not    sign            ;  yup.  flip signs
  296.     neg    edx            ;   ...
  297. divides1:
  298.     cmp    ebx,0            ; is Y negative?
  299.     jge    short divides2        ;  nope
  300.     not    sign            ;  yup.  flip signs
  301.     neg    ebx            ;   ...
  302. divides2:
  303.  
  304.     mov    eax,0            ; clear out the low-order bits
  305.     mov    cx,32            ; set up the shift
  306.     sub    cx,n            ; (for large shift counts - faster)
  307. fastd1: cmp    cx,0            ; done shifting?
  308.     je    fastd2            ; yup.
  309.     shr    edx,1            ; shift one bit
  310.     rcr    eax,1            ;  ...
  311.     loop    fastd1            ; and try again
  312. fastd2:
  313.     cmp    edx,ebx         ; umm, will the divide blow out?
  314.     jae    overd1            ;  yup.  better skip it.
  315.     div    ebx            ; do the divid